n个小球放入m个盒子中_M个球放入N个盒子的放法

M个球放入N个盒子的放法

1、N个盒子编号为1到N, 把M个相同的球放入这N个不相同的盒子,问共有多少种放法。

M个球分成了N组,即装入N个盒子。如果要求每个盒子至少有一个球,则要求M>=N.

M个球排成一排,中间有M-1个空隙, 任选N-1个空隙放挡板,即分成N组, 放法总数为:C(M-1,N-1) 。

2、N=3时,特例

1)将M个球放入3个不同的盒子共有X(M)=C(M-1,2)种方法;

2)其中有两个即以上盒子中的球数目相同的情况,共有Y(M)=[(M-1)/2]中,[*]表示取整。如果M是3的倍数,则包含1种三个盒子中球数目都相同,否则没有。令Z(M)=1,如果Mmod3=0,否则Z=0;下面考虑如下事实:

l 两个盒子球数目相同,如果盒子不同,相同的一组数有3中组合,即任选一个盒子放入那个不同的数,另外两个盒子一样,C(3,1)=3;

l 三个盒子球数目相同,不管盒子相同或不同都只有一种放法;

l 三个盒子中球数目都不同,一组数由于盒子不同而带来的组合有P(3)=3*2*1=6种。

因此盒子不同时总的放法为X,其中有3(Y-Z)中是两个及以上盒子球相同的放法,Z种三个盒子球数目相同的放法,剩余的为三个盒子球数目都不相同的放法,即X-3*(Y-Z)-Z。

3)当盒子不做区分时,

l 两个盒子球数目相同的情况有Y-Z种;

l 三个盒子数目相同的情况有Z种;

l 三个盒子数目都不相同的情况有X-3*(Y-Z)-Z;

因此当盒子不做区分时,将M个球放入3个盒子的总的放法为:

A=Z(M)+(Y(M)-Z(M))+{X(M)-3*[Y(M)-Z(M)]-Z(M)}/6

M=15时,Z(M)=1, Y(M)=7, X(M)=91,

所以A=1+(7-1)+{91-3*[7-1]-1}/6=7+72/6=19

2、N=3时,M=15时特例

当M=15时可以用穷举法。

方法一:推理。令X+Y+Z=15, X<=Y<=Z

当X=1时,Y+Z=14,Y=1~7,共7种;

当X=2时,Y+Z=13,Y=2~6,共5种;

当X=3时,Y+Z=12,Y=3~6,共4种;

当X=4时,Y+Z=11,Y=4~5,共2种;

当X=5时,Y+Z=10,Y=5,共1种;

总计:7+5+4+2+1=19种,

方法二:图解

总计:7+5+4+2+1=19种。

arrb[i]表示第i个盒子是否已经放入小球(1表示已经放入,0表示未放入)。现在需要找到一个未被检查过的盒子,将小球放入,使得放入小球后,所有盒子放入小球的数量都不相同。若存在多个未被检查过的盒子都可以满足要求,则选择编号最小的盒子放入小球。 解决思路: 1.遍历数组arrb,将所有已经放入小球盒子对应的位置在数组arra标记为1; 2.遍历数组arra,找到第一个未被检查过的盒子,标记为当前最小盒子; 3.从最小盒子开始,向后遍历数组arra,找到第一个未被检查过的盒子,将其标记为当前比当前最小盒子放入小球后,放入小球的数量最少的盒子; 4.继续遍历数组arra,找到所有未被检查过的盒子放入小球后,放入小球的数量最少的盒子; 5.将小球放入最终找到的盒子,更新数组arrb对应位置的值为1,表示该盒子已经放入小球; 6.返回最终找到的盒子编号。 代码实现: int findBox(int n, int a, int* arra, int* arrb) { int minBox = -1; //当前最小盒子 int minNum = INT_MAX; //放入小球后,放入小球的数量最少的盒子小球数量 int numCount[n + 1]; //用于记录每个盒子放入小球的数量 memset(numCount, 0, sizeof(numCount)); //初始化为0 for(int i = 1; i <= n; i++) { if(arrb[i] == 1) { arra[i - 1] = 1; //标记为已经检查过 numCount[i]++; //更新放入小球的数量 } } for(int i = 0; i < n; i++) { if(arra[i] == 0) { //找到第一个未被检查过的盒子 minBox = i + 1; break; } } for(int i = minBox + 1; i <= n; i++) { //从最小盒子开始遍历 if(arra[i - 1] == 0) { //找到未被检查过的盒子 int ballNum = numCount[i]; //放入小球后,放入小球的数量 if(ballNum < minNum) { //更新放入小球后,放入小球的数量最少的盒子 minBox = i; minNum = ballNum; } } } for(int i = minBox + 1; i <= n; i++) { //继续遍历数组arra,找到所有未被检查过的盒子放入小球后,放入小球的数量最少的盒子 if(arra[i - 1] == 0) { int ballNum = numCount[i]; if(ballNum == minNum) { minBox = i; } } } arrb[minBox] = 1; //将小球放入最终找到的盒子 return minBox; }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值